package databaseTransaction;

import java.sql.SQLException;
import java.util.List;

import util.ConnectionConfig;
import util.Relationship;
import util.UserTerminatingException;

import lexer.TokenConstant;

public class ModelLayer {
	private List<Table> tables;
	private DatabaseTransaction dbTransaction;

	public ModelLayer(ConnectionConfig connConfig) {
		dbTransaction = new DatabaseTransaction(connConfig);
	}

	public void setTables(List<Table> tables) {
		this.tables = tables;
	}

	public List<Table> getTables() {
		return this.tables;
	}

	public void addTable(Table table) {
		tables.add(table);
	}

	public void checkExistTable() throws SQLException, UserTerminatingException {
		for(Table tbl : this.tables){
			if(dbTransaction.isTableExist(tbl.getName())){
				tbl.setExist(true);
				OverideChooser isOveride = new OverideChooser(tbl);
				while (isOveride.isDisplayable())
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				System.out.println(isOveride.isCancel());
				if (isOveride.isCancel())
					throw new UserTerminatingException();
					
			}
		}
	}
	
	public void createTable() throws SQLException, UserTerminatingException {
		this.checkExistTable();
		for (Table tbl : tables) 
			if (tbl.isExist()){
				if (tbl.isOveride()){
					excuteCreate(tbl);
					setPK(tbl);
				}
				else
					dbTransaction.mergeExistTable(tbl);
			}		
			else{
				excuteCreate(tbl);
				setPK(tbl);
			}

		for (Table tbl : tables) {
			this.setFK(tbl);

			List<TableField> ids = tbl.getId();
			for (TableField id : ids)
				if (id.getRelationship() != null) {
					Relationship relationship = id.getRelationship();
					if (relationship.getRelationship() == TokenConstant.MANYTOMANY) {
						addRelationshipToTableField(relationship, tbl.getName());
					}

					else if (relationship.getRelationship() == TokenConstant.ONETOMANY) {

					}
				}
		}
	}

	private void addRelationshipToTableField(Relationship relationship,
			String ownRelationTableName) {
		String tableName = relationship.getTableName();
		String tableFieldName = relationship.getTableFieldName();

		for (Table tbl : tables) {
			if (tbl.getName().equals(tableName)) {
				List<TableField> ids = tbl.getId();
				if (ids.size() == 0)
					return;
				for (TableField id : ids) {
					if (id.getName().equals(tableFieldName)) {
						if (relationship.getRelationship() != TokenConstant.MANYTOMANY)
							id.setRelationship(relationship);
						else {
							Relationship otherRelationship = new Relationship();
							otherRelationship.setRelationship(relationship
									.getRelationship());

							otherRelationship
									.setTableName(ownRelationTableName);
							otherRelationship.setTableFieldName(relationship
									.getTableFieldName());
							otherRelationship
									.setOtherTableFieldName(relationship
											.getOtherTableFieldName());
							otherRelationship.setOtherTableName(relationship
									.getOtherTableName());

							id.setRelationship(otherRelationship);
						}
					}
				}
			}
		}
	}

	private void excuteCreate(Table table) throws SQLException {
		try {
			if (table.isExist())
				dbTransaction.dropExistTable(table.getName());
			dbTransaction.excuteCreate(table);
		} catch (SQLException e) {
			throw e;
		}
	}

	private void setPK(Table table) throws SQLException {
		dbTransaction.setPK(table); // Set PK with all id fields
		for (TableField idField : table.getId()) {
			if (idField.getExtra().contains(TokenConstant.AUTOINCREASE))
				dbTransaction.setAutoIncrease(table.getName(),
						idField.getName());
		}
	}

	// change
	private void setFK(Table table) throws SQLException {
		for (TableField tblField : table.getTableFields()) {
			if (!tblField.getExtra().isEmpty()) {
				if (tblField.getExtra().contains(TokenConstant.FK)) {
					dbTransaction.setFK(table.getName(), tblField.getName(),
							(String) tblField.getExtra().get(2),
							(String) tblField.getExtra().get(1));
				}
			}
		}
	}
}
